package cn.kerui.manage.service.sys.impl;

import cn.kerui.common.enums.BaseExceptionMsg;
import cn.kerui.common.exception.ServiceException;
import cn.kerui.common.framework.util.lang.CollectionUtil;
import cn.kerui.common.framework.util.lang.NumberUtil;
import cn.kerui.common.framework.util.lang.StringUtil;
import cn.kerui.common.framework.util.validation.Assert;
import cn.kerui.common.redis.constants.RedisCacheConstants;
import cn.kerui.common.redis.helper.RedisHelper;
import cn.kerui.manage.constants.ManageExceptionMsg;
import cn.kerui.manage.service.sys.DicStanService;
import cn.kerui.manage.vo.sys.CataLogVO;
import cn.kerui.repos.entities.sys.SysDicCatalog;
import cn.kerui.repos.entities.sys.SysDicStan;
import cn.kerui.repos.mapper.sys.SysDicCatalogMapper;
import cn.kerui.repos.mapper.sys.SysDicStanMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p> 字典相关业务实现层 </p>
 * <p>创建于 2024/1/12 14:59 </p>
 *
 * @author yangkai
 * @version v1.0
 * @since 1.0.0
 */
@Service
@AllArgsConstructor
@Slf4j
public class DicStanServiceImpl implements DicStanService {

    private SysDicCatalogMapper dicCatalogMapper;

    private SysDicStanMapper dicStanMapper;

    private RedisHelper redisHelper;

    /**
     * 查询字典目录
     */
    @Override
    public List<CataLogVO> getCatalogList() {
        List<SysDicCatalog> sysDicCatalogs = dicCatalogMapper.selectList(null);
        List<CataLogVO> list = sysDicCatalogs.stream().map(CataLogVO::new).toList();
        list.forEach(e -> e.setChildNum(NumberUtil.safeToInteger(getChildNum(e.getCode()))));
        return list;
    }

    /**
     * 根据目录ID查询字典列表
     */
    @Override
    public List<SysDicStan> getDicStanByCatalogId(String dicCode) {
        return dicStanMapper.selectList(new LambdaQueryWrapper<>(SysDicStan.class)
                .eq(SysDicStan::getDicCode, dicCode));
    }

    /**
     * 批量获取字典信息
     * @param dicCodes 多个字典编码用逗号分割
     */
    @Override
    public Map<String, List<SysDicStan>> getDicStanBatch(String dicCodes) {
        List<String> dicCodeList = StringUtil.split(dicCodes, StringUtil.COMMA);

        Optional.ofNullable(dicCodeList)
                        .orElseThrow(() -> new ServiceException(BaseExceptionMsg.PARAM_INVALID));

        List<SysDicStan> sysDicStans = dicStanMapper.selectList(new LambdaQueryWrapper<>(SysDicStan.class)
                .in(SysDicStan::getDicCode, dicCodeList));

        if (CollectionUtil.isEmpty(sysDicStans)) {
            log.warn("未查询到任何字典信息, {}", dicCodes);
            return null;
        }

        return sysDicStans.stream().collect(Collectors.groupingBy(SysDicStan::getDicCode));
    }

    /**
     * 删除字典目录
     */
    @Override
    public void deleteDicCatalog(String dicCode) {
        // 校验该字典目录下是否存在字典
        Long childNum = getChildNum(dicCode);

        if (childNum > 0) {
            throw new ServiceException(ManageExceptionMsg.DIC_CATALOG_NOT_EMPTY);
        }

        dicCatalogMapper.deleteById(dicCode);
        // 删除字典缓存
        redisHelper.delCacheByRedisKey(RedisCacheConstants.COMMON_DIC_CACHE, dicCode);
        // TODO 发布操作记录
    }

    /**
     * 新增字典目录
     * @param sysDicCatalog 字典目录实体
     */
    @Override
    public void insertDicCatalog(SysDicCatalog sysDicCatalog) {
        // 验证当前字典目录是否存在
        boolean exists = dicCatalogMapper.exists(new LambdaQueryWrapper<>(SysDicCatalog.class)
                .eq(SysDicCatalog::getDicCode, sysDicCatalog.getDicCode()));

        Assert.isFalse(exists, () -> new ServiceException(ManageExceptionMsg.DIC_CATALOG_EXIST));

        dicCatalogMapper.insert(sysDicCatalog);

        // TODO 发布操作记录
    }

    /**
     * 更新字典目录
     */
    public void updateDicCatalog(SysDicCatalog sysDicCatalog) {
        // 验证当前字典目录是否存在
        boolean exists = dicCatalogMapper.exists(new LambdaQueryWrapper<>(SysDicCatalog.class)
                .eq(SysDicCatalog::getDicCode, sysDicCatalog.getDicCode()));

        Assert.isTrue(exists, () -> new ServiceException(ManageExceptionMsg.DIC_CATALOG_NOT_EXIST));
        // 更新字典目录
        dicCatalogMapper.updateById(sysDicCatalog);

        // TODO 发布操作记录
    }

    /**
     * 删除字典条目
     */
    @Override
    public void deleteDicStan(Long id) {
        // 查询字典条目是否存在
        SysDicStan sysDicStan = dicStanMapper.selectById(id);
        Assert.isNotNull(sysDicStan, () -> new ServiceException(ManageExceptionMsg.DIC_STAN_NOT_EXIST));

        dicStanMapper.deleteById(id);
        // 删除字典缓存
        redisHelper.delCacheByRedisKey(RedisCacheConstants.COMMON_DIC_CACHE, sysDicStan.getDicCode());

        // TODO 发布操作记录
    }

    /**
     * 新增字典条目
     * @param sysDicStan 字典条目实体
     */
    @Override
    public void insertDicStan(SysDicStan sysDicStan) {
        // 查询字典目录是否存在
        boolean exists = dicCatalogMapper.exists(new LambdaQueryWrapper<>(SysDicCatalog.class)
                .eq(SysDicCatalog::getDicCode, sysDicStan.getDicCode()));
        Assert.isTrue(exists, () -> new ServiceException(ManageExceptionMsg.DIC_CATALOG_NOT_EXIST));

        List<SysDicStan> sysDicStans = dicStanMapper.selectList(new LambdaQueryWrapper<>(SysDicStan.class)
                .eq(SysDicStan::getDicCode, sysDicStan.getDicCode()));

        // 判断字典条目是否存在
        if (CollectionUtil.isNotEmpty(sysDicStans)) {
            Assert.isFalse(sysDicStans.stream().anyMatch(stan -> stan.getValue().equals(sysDicStan.getValue())),
                    () -> new ServiceException(ManageExceptionMsg.DIC_STAN_EXIST));
        }


        dicStanMapper.insert(sysDicStan);

        // 删除字典缓存
        redisHelper.delCacheByRedisKey(RedisCacheConstants.COMMON_DIC_CACHE, sysDicStan.getDicCode());
        // TODO 发布操作记录
    }

    /**
     * 更新字典条目
     * @param sysDicStan
     */
    @Override
    public void updateDicStan(SysDicStan sysDicStan) {
        SysDicStan dbDicStan = dicStanMapper.selectById(sysDicStan.getId());
        Assert.isNotNull(dbDicStan, () -> new ServiceException(ManageExceptionMsg.DIC_STAN_NOT_EXIST));
        dicStanMapper.updateById(sysDicStan);
        // 删除字典缓存
        redisHelper.delCacheByRedisKey(RedisCacheConstants.COMMON_DIC_CACHE, sysDicStan.getDicCode());
        // TODO 发布操作记录
    }


    /**
     * 查询字典目录下的字典数量
     *
     * @param dicCode 字典编码
     * @return 字典条目数量
     */
    private Long getChildNum(String dicCode) {

        return dicStanMapper.selectCount(new LambdaQueryWrapper<>(SysDicStan.class)
                .eq(SysDicStan::getDicCode, dicCode));
    }
}
